/**
 * @file server.cpp
 * @author zeppyrz (zeppyrz@gamil.com)
 * @brief test libevent Server
 * @version 0.1
 * @date 2025-11-02
 *
 * @copyright Copyright (c) 2025
 *
 */

#include <string.h>

#include "FtpCMD.h"
#include "ThreadPool.h"
#ifdef _WIN32
#  include <winsock2.h>
#  include <windows.h>
#else
#  include <arpa/inet.h>
#  include <sys/socket.h>
#endif
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/util.h>

#include <csignal>
#include <iostream>

void accept_cb(evconnlistener *, evutil_socket_t, sockaddr *, int socklen,
               void *);
void event_cb(struct bufferevent *bev, short what, void *ctx);
void signal_cb(evutil_socket_t sig, short events, void *user_data) {
  event_base *base = (event_base *)user_data;
  timeval delay = {2, 0};
  printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
  event_base_loopexit(base, &delay);
}

int main(int argc, char *argv[]) {
#ifdef _WIN32
  WSADATA wsadata;
  WSAStartup(MAKEWORD(2, 2), &wsadata);
#else
  // 忽略管道信号
  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) return 1;
#endif
  // 初始化线程池
  ZeDisk::ThreadPool::GetInstance().Init(8);

  int port = 2048;
  if (argc > 2) {
    port = atoi(argv[2]);
  }

  // 创建libevent 上下文
  // 默认创建base锁
  event_base *base = event_base_new();
  if (!base) {
    std::cout << "event_base_new() failed" << std::endl;
    return 1;
  }

  sockaddr_in sin;
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  sin.sin_port = htons(port);

  evconnlistener *listener = evconnlistener_new_bind(
      base, accept_cb, base, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1,
      (sockaddr *)&sin, sizeof(sin));

  if (!listener) {
    std::cout << "evconnlistener_new_bind() failed" << std::endl;
    return 1;
  }
  std::cout << "Listening on port " << port << std::endl;

  auto *sigev = evsignal_new(base, SIGINT, signal_cb, (void *)base);
  if (!sigev || event_add(sigev, nullptr) < 0) {
    std::cout << "evsignal_new() failed" << std::endl;
    return 1;
  }

  // 事件分发 (event loop)
  event_base_dispatch(base);

  /*
  event_del(ev);
  event_free(ev);
  */
  event_del(sigev);
  event_free(sigev);
  event_base_free(base);
  return 0;
}
void accept_cb(evconnlistener *listener, evutil_socket_t fd, sockaddr *sin,
               int socklen, void *user_data) {
  std::cout << "accept_cb() called" << std::endl;

  auto *task = new ZeDisk::FtpCMD(fd);
  ZeDisk::ThreadPool::GetInstance().Dispatch(task);
}